package vn.pdg.zoombie.bussiness;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import vn.pdg.zoombie.bean.Utils;
import vn.pdg.zoombie.common.LogDebug;
import vn.pdg.zoombie.dao.FileCache;
import vn.pdg.zoombie.dao.MemoryCache;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.media.ExifInterface;
import android.widget.ImageView;

public class ImageLoader {
    
	private String TAG = "ImageLoader";
    private MemoryCache memoryCache=new MemoryCache();
    private FileCache fileCache;
    private Map<ImageView, String> imageViews=Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
    private ExecutorService executorService; 
    
    private int typeImageLoader;
    public static int TYPE_FROM_DIS 		= 0;
    public static int TYPE_FROM_INTERNET 	= 1;
    private final int SIZE_IMAGE_DECODE 		= 100;
    
    
    public ImageLoader(Context context, int typeImageLoader){
    	this.typeImageLoader = typeImageLoader;
        fileCache=new FileCache(context);
        executorService=Executors.newFixedThreadPool(5);
    }
    
    //final int stub_id=R.drawable.stub;
    public void DisplayImage(String url, ImageView imageView, int degrees)
    {
        imageViews.put(imageView, url);
        Bitmap bitmap=memoryCache.get(url);
        if(bitmap!=null)
            imageView.setImageBitmap(bitmap);
        else
        {
            queuePhoto(url, imageView, degrees);
          //  imageView.setImageResource(stub_id);
        }
    }
        
    private void queuePhoto(String url, ImageView imageView, int degrees)
    {
        PhotoToLoad p=new PhotoToLoad(url, imageView,degrees);
        executorService.submit(new PhotosLoader(p));
    }
    

    private Bitmap getImageFromDis(String url, int degrees){
    	try {
			Bitmap b;
			ExifInterface exif;

			exif = new ExifInterface(url);

			if (exif.hasThumbnail()) {
				LogDebug.d(TAG, "has thumbails ...");
				byte[] data = exif.getThumbnail();
				b = BitmapFactory.decodeByteArray(data, 0, data.length);

				if (b != null)
					return b;
				
				LogDebug.d(TAG, "has thumbails");

			}

			// get file local thumbs of image
			File localThumbs = fileCache.getFile(url);

			// decode file thumbs
			b = Utils.decodeFile(localThumbs, SIZE_IMAGE_DECODE);

			if (b != null) {
				return b;
			}
			// file root image
			File localFile = new File(url);

			Utils.createSquareThumnails(localFile, localThumbs,
					SIZE_IMAGE_DECODE, degrees);

			b = Utils.decodeFile(localThumbs, SIZE_IMAGE_DECODE);

			return b;
		} catch (Exception e) {
			// TODO: handle exception
			return null;
		}
    }
    
    private Bitmap getImageFromInternet(String url){
    	Bitmap bitmap = null;
    	try {
    		bitmap = downloadImage(url);
		} catch (IOException e) {
			// TODO Auto-generated catch block
		}
    	
    	return bitmap;
    	
    }
    
	/**
	 * @author dieudv Method convert stream to byte array
	 * @param is
	 *            {@link InputStream}
	 * @return byte[]
	 */
	public byte[] convertInputStreamToByteArray(InputStream is)
			throws IOException {
		BufferedInputStream bis = new BufferedInputStream(is, 1024);
		ByteArrayOutputStream buf = new ByteArrayOutputStream();
		int result = bis.read();
		while (result != -1) {
			byte b = (byte) result;
			buf.write(b);
			result = bis.read();
		}
		return buf.toByteArray();
	}

	/**
	 * Method is downloading image with url of image
	 * 
	 * @author dieudv
	 * @param stringurl
	 *            {@link String} is url of image
	 * @return {@link Bitmap}
	 * @throws IOException 
	 * */
	public Bitmap downloadImage(String stringurl) throws IOException {
		InputStream in = null;
		HttpURLConnection connection = null;
		Bitmap bitmap = null;
		URL url = null;

			url = new URL(stringurl);
			connection = (HttpURLConnection) url.openConnection();
			connection.setDoInput(true);
			connection.setReadTimeout(2000);

			in = connection.getInputStream();

			byte[] by = convertInputStreamToByteArray(in);

			Options option = new Options();
			option.inTempStorage = new byte[1024];
			bitmap = BitmapFactory.decodeByteArray(by, 0, by.length, option);
		return bitmap;

	}
    
    private Bitmap getBitmap(String url, int degrees) 
    {
    	if(typeImageLoader == TYPE_FROM_DIS)
    		return getImageFromDis(url, degrees);
    	else
    		return getImageFromInternet(url);
	}

    //Task for the queue
    private class PhotoToLoad
    {
        public String url;
        public ImageView imageView;
        public int degrees;
        public PhotoToLoad(String u, ImageView i, int degree){
            url=u; 
            imageView=i;
            degrees = degree;
        }
    }
    
    class PhotosLoader implements Runnable {
        PhotoToLoad photoToLoad;
        PhotosLoader(PhotoToLoad photoToLoad){
            this.photoToLoad=photoToLoad;
        }
        
        @Override
        public void run() {
            if(imageViewReused(photoToLoad))
                return;
            Bitmap bmp=getBitmap(photoToLoad.url,photoToLoad.degrees);
            memoryCache.put(photoToLoad.url, bmp);
            if(imageViewReused(photoToLoad))
                return;
            BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad);
            Activity a=(Activity)photoToLoad.imageView.getContext();
            a.runOnUiThread(bd);
        }
    }
    
    boolean imageViewReused(PhotoToLoad photoToLoad){
        String tag=imageViews.get(photoToLoad.imageView);
        if(tag==null || !tag.equals(photoToLoad.url))
            return true;
        return false;
    }
    
    //Used to display bitmap in the UI thread
    class BitmapDisplayer implements Runnable
    {
        Bitmap bitmap;
        PhotoToLoad photoToLoad;
        public BitmapDisplayer(Bitmap b, PhotoToLoad p){bitmap=b;photoToLoad=p;}
        public void run()
        {
            if(imageViewReused(photoToLoad))
                return;
            if(bitmap!=null)
                photoToLoad.imageView.setImageBitmap(bitmap);
           // else
            //    photoToLoad.imageView.setImageResource(stub_id);
        }
    }

    public void clearCache() {
        memoryCache.clear();
        //fileCache.clear();
    }

    public void clearCacheFile(){
    	fileCache.clear();
    }
}
